import {
  enable as remoteEnable,
  initialize as remoteInit,
} from "@electron/remote/main";
import {
  app,
  BrowserWindow,
  BrowserWindowConstructorOptions,
  ipcMain,
  session,
  WebContents,
} from "electron";
import _ from "lodash";
import Path from "path";
try {
  remoteInit();
} catch (error) {
  //
}

/**
 * 在app.isPackaged===false时安装vue-devtools
 * @link https://gitee.com/mirrors/vue-devtools?_from=gitee_search
 */
export function installVueDevTools() {
  if (!app.isPackaged) {
    session.defaultSession.loadExtension(
      Path.resolve(__dirname, "../assets/vue-devtools")
    );
  }
}

/**
 * 默认的electronWindow设定
 * @example
 * {useContentSize: true
 * autoHideMenuBar: true
 * webPreferences: {
    // preload: Path.join(__dirname, "../preloads/index.js"),
    nodeIntegration: true,
    nodeIntegrationInSubFrames: true,
    nodeIntegrationInWorker: true,
    webSecurity: false,
    // @ts-ignore
    allowDisplayingInsecureContent: true,
    allowRunningInsecureContent: true,
    // contextIsolation: !isLocalhost(url), // Preload本身可以访问页面中的内容
  }}
 */
export const defaultElectronWindowOptions: BrowserWindowConstructorOptions = {
  // width: 800,
  // height: 600,
  useContentSize: true,
  // resizable: true,
  // frame: true,
  // closable: true,
  // maximizable: true,
  autoHideMenuBar: true,
  webPreferences: {
    // preload: Path.join(__dirname, "../preloads/index.js"),
    nodeIntegration: true,
    nodeIntegrationInSubFrames: true,
    nodeIntegrationInWorker: true,
    webSecurity: false,
    // @ts-ignore
    allowDisplayingInsecureContent: true,
    allowRunningInsecureContent: true,
    // contextIsolation: !isLocalhost(url), // Preload本身可以访问页面中的内容
  },
};

/**
 * 在渲染进程中可以使用@electron/remote模块
 * @param {object}webContents win.webContents
 */
export function enableWebRemote(webContents: WebContents) {
  remoteEnable(webContents);
}

/**
 * 启动一个BrowserWindow
 * @param 选项
 * @returns {BrowserWindow} 返回BrowserWindow实例
 */
export function createBrowserWindow({
  url,
  mode = "loadURL",
  config = _.cloneDeep(defaultElectronWindowOptions),
  setConfig,
}: {
  /** 打开窗口的url或者html文件 */
  url: string;
  /** 打开url用的函数 */
  mode?: "loadFile" | "loadURL";
  /** BrowserWindow(里面的选项)
   * @link https://www.electronjs.org/zh/docs/latest/api/browser-window#new-browserwindowoptions
   */
  config?: BrowserWindowConstructorOptions;
  /**
   * 对config进行设置
   * @link https://www.electronjs.org/zh/docs/latest/api/browser-window#new-browserwindowoptions
   */
  setConfig?: (
    config: BrowserWindowConstructorOptions
  ) => BrowserWindowConstructorOptions;
}): BrowserWindow {
  setConfig && setConfig(config);
  let win = new BrowserWindow(setConfig ? setConfig(config) : config);
  const { webContents } = win;
  enableWebRemote(webContents);
  app.isPackaged || webContents.openDevTools({ mode: "undocked" });
  webContents.setUserAgent(
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55"
  );
  win[mode](url);
  return win;
}

export async function appStart({
  firstly = () => 0,
  onActivate = () => {},
  onAllClosed = (num: number) => num || app.exit(),
}: {
  /**
   * 在程序启动前运行的函数
   */
  firstly?: () => any;
  /**
   * app activate 时运行的函数
   */
  onActivate?: (
    /**
     * 剩余的窗口数量
     */
    num: number
  ) => any;
  /**
   * window-all-closed 时运行的函数(必须是同步函数)
   */
  onAllClosed?: (
    /**
     * 剩余的窗口数量
     */
    num: number
  ) => any;
}): Promise<true> {
  try {
    firstly();
    await app.whenReady();
    app.commandLine.appendSwitch("disable-features", "OutOfBlinkCors");
    app.commandLine.appendSwitch("disable-site-isolation-trials");
    app.commandLine.appendSwitch("ignore-certificate-errors");
    app.on("activate", () => {
      onActivate(BrowserWindow.getAllWindows().length);
    });
    app.on("window-all-closed", () => {
      onAllClosed(BrowserWindow.getAllWindows().length);
    });
  } catch (error) {
    app.exit();
  }
  return true;
}

export interface IpcMainHandlerSync {
  /**
   * 定义一个路径
   */
  route: string;
  /**
   * @returns 向renderer发送的消息
   */
  func: (data: any) => void | any;
}
export function handleIpcMainSync(handlers: IpcMainHandlerSync[] = []): void {
  ipcMain.on("synchronous-message", (event, { route, data }) => {
    for (let handler of handlers) {
      if (handler.route === route) {
        event.returnValue = handler.func(data);
      }
    }
  });
}
